package com.zatech.cgnci.project.base.exception.handle;

import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;


/**
 * 全局异常捕获
 *
 * @author edy
 */
@RestControllerAdvice
public class ExceptionHandle {

    private final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);

    /**
     * GlobalException
     */
    @ExceptionHandler(value = GlobalException.class)
    public Object globalException(HttpServletRequest request, GlobalException exception) {
        logger.error("全局异常 请求地址: {}, [Global Exception Interception] GlobalException: Code {}, Message {}", request.getRequestURI(), exception.getErrorCode(), exception.getMessage(), exception);
        return new Result<>(exception.getErrorCode(), exception.getMessage());
    }

    /**
     * DuplicateKeyException
     */
    @ExceptionHandler(value = DuplicateKeyException.class)
    public Object duplicateKeyException(HttpServletRequest request, DuplicateKeyException exception) {
        logger.error("数据重复异常 请求地址: {}", request.getRequestURI(), exception);
        return new Result<>(ResponseCodeEnum.DUPLICATE_KEY_ERROR);
    }

    /**
     * MultipartException
     */
    @ExceptionHandler(value = MultipartException.class)
    public Object multipartException(HttpServletRequest request, MultipartException exception) {
        logger.error("文件上传异常 请求地址: {}", request.getRequestURI(), exception);
        return new Result<>(ResponseCodeEnum.MULTIPART_ERROR);
    }

    /**
     * BadSqlGrammarException
     */
    @ExceptionHandler(value = BadSqlGrammarException.class)
    public Object badSqlGrammarException(HttpServletRequest request, BadSqlGrammarException exception) {
        logger.error("错误SQL异常 请求地址: {}", request.getRequestURI(), exception);
        return new Result<>(ResponseCodeEnum.BAD_SQL_GRAMMAR_ERROR);
    }

    /**
     * SQLException
     */
    @ExceptionHandler(value = SQLException.class)
    public Object sqlException(HttpServletRequest request, SQLException exception) {
        logger.error("数据库操作异常 请求地址: {}", request.getRequestURI(), exception);
        return new Result<>(ResponseCodeEnum.SQL_ERROR);
    }

    /**
     * IllegalArgumentException
     */
    @ExceptionHandler({IllegalArgumentException.class, HttpMessageNotReadableException.class})
    public Object illegalArgumentException(HttpServletRequest request, RuntimeException exception) {
        String message = exception.getMessage();
        logger.error("非法参数异常 请求地址: {}, [Global Exception Interception] IllegalArgumentException: Exception Message {}", request.getRequestURI(), message, exception);
        return new Result<>(ResponseCodeEnum.PARAMS_ILLEGAL, message);
    }

    /**
     * NullPointerException
     */
    @ExceptionHandler(value = NullPointerException.class)
    public Object nullPointerException(HttpServletRequest request, NullPointerException exception) {
        logger.error("空指针异常 请求地址: {}, [Global Exception Interception] NullPointerException: Exception Message {}", request.getRequestURI(), exception.getMessage(), exception);
        return new Result<>(ResponseCodeEnum.SERVICE_ERROR, exception.getMessage());
    }

    @ExceptionHandler(value = BindException.class)
    public Object bindException(HttpServletRequest request, BindException exception) {
        String message = exception.getBindingResult()
                .getAllErrors()
                .get(0)
                .getDefaultMessage();
        logger.error("参数绑定系统异常 请求地址: {}, [Global Exception Interception] BindException: Error Message {}", request.getRequestURI(), message, exception);
        return new Result<>(ResponseCodeEnum.SERVICE_ERROR, message);
    }


    @ExceptionHandler(value = ConstraintViolationException.class)
    public Object constraintViolationException(HttpServletRequest request, ConstraintViolationException exception) {
        String message = exception.getConstraintViolations().iterator().next().getMessage();
        logger.error("参数校验异常 请求地址: {}, request.getRequestURI()[Global Exception Interception] ConstraintViolationException: Error Message {}", request.getRequestURI(), message, exception);
        return new Result<>(ResponseCodeEnum.SERVICE_ERROR, message);
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Object methodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException exception) {
        String message = exception.getBindingResult()
                .getAllErrors()
                .get(0)
                .getDefaultMessage();
        logger.error("参数绑定系统异常 请求地址: {}, [Global Exception Interception] MethodArgumentNotValidException: Error Message {}", request.getRequestURI(), message, exception);
        return new Result<>(ResponseCodeEnum.SERVICE_ERROR, message);
    }

    /**
     * other Exception
     */
    @ExceptionHandler(value = Exception.class)
    public Object exception(HttpServletRequest request, Exception exception) {
        logger.error("系统异常 请求地址: {}", request.getRequestURI(), exception);
        return new Result<>(ResponseCodeEnum.SERVICE_ERROR);
    }

}
